package com.baigt.j8.stream;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import static java.util.stream.Collector.Characteristics.*;

public class StreamCustomCollector2 {
    public static void main(String[] args) {
//        Map<String, String> map = Arrays.asList("ricky", "baigt", "weiyi").stream().collect(new CustomCollector2<String>());

//        Map<String, String> map = Arrays.asList("ricky", "baigt", "weiyi", "ricky1", "baigt1", "weiyi1").parallelStream().collect(new CustomCollector2<String>());
//        map.forEach((key, val) -> {
//            System.out.println(String.format("key:%s,val:%s", key, val));
//        });

        for (int i = 0; i < 1; i++) {
//            Map<String, String> map = Arrays.asList("ricky", "baigt", "weiyi", "ricky1", "baigt1", "weiyi1").stream().collect(new CustomCollector2<String>());
            Map<String, String> map = Arrays.asList("ricky", "baigt", "weiyi", "ricky1", "baigt1", "weiyi1").parallelStream().collect(new CustomCollector2<String>());
        }
    }
}

class CustomCollector2<E> implements Collector<E, Set<E>, Map<E, E>> {

    @Override
    public Supplier<Set<E>> supplier() {
        System.out.println("supplier invoke");
        return HashSet::new;
    }

    @Override
    public BiConsumer<Set<E>, E> accumulator() {
        System.out.println("accumulator invoke ");
        return (sets, e) -> {
            System.out.println(String.format("sets:%s,threadName:%s", sets, Thread.currentThread().getName()));
            sets.add(e);
        };
    }

    @Override
    public BinaryOperator<Set<E>> combiner() {
        System.out.println("combiner invoke");
        return (sets1, sets2) -> {
            System.out.println("combiner function invoke");
            sets1.addAll(sets2);
            return sets1;
        };
    }

    @Override
    public Function<Set<E>, Map<E, E>> finisher() {
        System.out.println("finisher invoke");
        return (set1) -> {
            Map map = new HashMap();
            set1.stream().forEach(set -> {
                map.put(set, set);
            });
            return map;
        };
    }

    @Override
    public Set<Characteristics> characteristics() {
        System.out.println("characterisstics invoke");
        // IDENTITY_FINISH  表示中间容器类型和finish的类型是一致的，在此例中表示，set<E>和Map<E,E>是一样的
        // CONSURRENT 表示并发操作（多个线程（parallelStream）只有一个中间容器（可以在(UNORDERED,CONCURRENT同时存在的情况下)看Combiner中的函数是否执行））,在并发操作时，可能会出现ConcurrentModificationException的异常
        // UNORDER  只有这一个特性的情况下，在parallelStream的场景下，会有多个中间容器，所以会执行combiner 中的function
        return Collections.unmodifiableSet(EnumSet.of(UNORDERED));
//        return Collections.unmodifiableSet(EnumSet.of(UNORDERED,CONCURRENT));
//        return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH));
    }
}
